home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Snippets / PNL Libraries / Libraries / MenuSharing / menusharing.c next >
Text File  |  1997-01-26  |  48KB  |  1,834 lines

  1.  
  2. /*© copyright 1991-96 UserLand Software, Inc. All Rights Reserved.*/
  3.  
  4.  
  5. /*
  6. Version 4.1:
  7. ------------
  8.  
  9. 7/17/96 dmb: Give client more control over menu insertion & deletion
  10.  
  11.     1. Frontier 4.1 now allows client to do actual menu insertion and 
  12.     deletion. Even for default operation, we use these callbacks so 
  13.     we can recover in the case of a server crash
  14.     
  15.     2. Added SetMenusInserterCallback and SetMenusRemoverCallback to allow
  16.     client to provide altername menu placement
  17.  
  18.     3. we override the server's default HandleMenuDirty event handler to 
  19.     insure its validity in the case of a server crash
  20.     
  21.     4. if the (component) server disappears unexpectedly, set fldirtysharedmenus
  22.  
  23. Version 3.0.2:
  24. --------------
  25.  
  26. 3/22/94 dmb: Updated for Universal Headers and Power PC.
  27.     
  28.     If you're using Think C/Symantec C++, make sure you're 
  29.     using the Universal Headers, not the headers that came on 
  30.     your program disks. Universal Headers are on the Macintosh 
  31.     on Risk SDK CD.
  32.  
  33. Version 3.0:
  34. ------------
  35.  
  36. 11/1/93 DW: Minor changes to support Frontier 3.0
  37.  
  38.     1. Frontier 3.0 implements an even more efficient menu sharing protocol
  39.     using the System 7.1 Component Manager. If possible, we use that protocol,
  40.     otherwise we are prepared to use the Frontier 2.0-compatible protocol, or
  41.     even the Frontier 1.0 protocol.
  42.     
  43.     2. Added a ComponentInstance field to the MSglobals struct. As with all 
  44.     other fields of MSglobals, this is read-only and really only there to 
  45.     support debugging..
  46.     
  47.     3. Added a procedure pointer field, scripterrorcallback, to the MSglobals 
  48.     struct to allow error reporting. It replaces scriptcompletedcallback. 
  49.     
  50.     4. Added a procedure pointer field, eventfiltercallback, to the MSglobals 
  51.     struct to allow error reporting. It allows the client app to handle 
  52.     update, activate, OS and null events while a script is running. 
  53.     
  54.     4. InitSharedMenus takes a parameter, a pointer to a routine that 
  55.     displays script error messages in a modal dialog
  56.     
  57.     5. Replaced calls to the IAC Tools library with direct calls to the 
  58.     Apple Event Manager. Apps no longer have to include any iacxxx.c files
  59.     in the project or #include <iac.h>.
  60.     
  61. 11/3/93 DW: Minor code cleanup
  62.     
  63.     1. Removed the #pragma from HandleMenuDirty.
  64.     
  65.     2. Edited the headers on several routines to conform to the prototypes-
  66.     required format. Allows this code to be compiled by the MetroWerks C++
  67.     compiler.
  68.     
  69.     3. Updated copyright notices in this file and in menusharing.h.
  70.     
  71. 11/4/93 DW: MPW-compatible & ifdefs
  72.  
  73.     6. built menusharing.c in MPW C. added #pragmas to head off warnings.
  74.     
  75.     7. implemented two ifdefs that allow you to turn off support for 
  76.     Frontier 2.0 and 1.0, or turn off support for component menu sharing.
  77.     
  78. 11/16/93 dmb: a tweak and a fix
  79.  
  80.     1. In the unlikely case that we're running on a system that supports 
  81.     recording, which requires the Component Manager, but the Apple Event- 
  82.     based protocol is being used, we set the DontRecord bit in the AESend 
  83.     mode flags. [Note: in case the AppleEvents.h header file is out of date, 
  84.     we #defined it, below (the value of this constant is 0x00001000).]
  85.     
  86.     2. In CheckSharedMenus, if the component instance has gone bad, clear out 
  87.     the menuserver global so that we'll try to reconnect the next time.
  88.  
  89. Version 2.0:
  90. ------------
  91.  
  92. 1/22/92 DW: provide for dialog on receipt of a 'done' message
  93.     
  94.     1. Frontier sets the 'errs' parameter if a shared script ended in an
  95.     error. we set up the IAC globals so that the scriptcomplete handler
  96.     can get the error string and display it in a dialog.
  97.     
  98. 6/29/92 DW: fast menu sharing if Frontier 2.0 is present.
  99.  
  100.     1. this is possible because Frontier 2.0 installs system event handlers
  101.     for the most time-consuming of the menu sharing operations.
  102.     
  103. 8/13/92 DW: cleaner way of killing scripts.
  104.     
  105.     1. In CancelSharedScript, we now send a message to the menu sharing server
  106.     asking that the script be killed. But only if we're talking to a server 
  107.     that supports fast messages.
  108. */
  109.  
  110.  
  111. #include <processes.h>
  112. #include <Menus.h>
  113. #include <Gestalt.h>
  114. #include "menusharing.h"
  115.  
  116. #define kAEDontRecord 0x00001000 /*this isn't defined in all versions of <AppleEvents.h>*/
  117.  
  118. #define componentMenuSharing /*undef this to disable component-based menu sharing.*/
  119.  
  120. #define frontierMenuSharing /*undef this to disable support for Frontier 1.0 and 2.0 menu sharing*/
  121.  
  122.  
  123. tyMSglobals MSglobals = {0, 0, nil, false, false, false, false, 0, 0, nil}; 
  124.  
  125. enum {
  126.     uppMSerrordialogProcInfo = kPascalStackBased
  127.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(char *)))
  128. };
  129.  
  130. enum {
  131.     uppMSeventfilterProcInfo = kPascalStackBased
  132.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(EventRecord *)))
  133. };
  134.  
  135. enum {
  136.     uppMSmenusinstallerProcInfo = kPascalStackBased
  137.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(hdlmenuarray)))
  138. };
  139.  
  140.  
  141. #if GENERATINGCFM
  142.     typedef UniversalProcPtr MSerrordialogUPP;
  143.     
  144.     #define CallMSerrordialogProc(userRoutine, theString)        \
  145.             CallUniversalProc((UniversalProcPtr)(userRoutine), uppMSerrordialogProcInfo, (theString))
  146.     #define NewMSerrordialogProc(userRoutine)        \
  147.             (MSerrordialogUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppMSerrordialogProcInfo, GetCurrentISA())
  148. #else
  149.     typedef tyMSerrordialog MSerrordialogUPP;
  150.     
  151.     #define CallMSerrordialogProc(userRoutine, theString)        \
  152.             (*(userRoutine))((theString))
  153.     #define NewMSerrordialogProc(userRoutine)        \
  154.             (MSerrordialogUPP)(userRoutine)
  155. #endif
  156.  
  157.  
  158. #if GENERATINGCFM
  159.     typedef UniversalProcPtr MSeventfilterUPP;
  160.     
  161.     #define CallMSeventfilterProc(userRoutine, theEvent)        \
  162.             CallUniversalProc((UniversalProcPtr)(userRoutine), uppMSeventfilterProcInfo, (theEvent))
  163.     #define NewMSeventfilterProc(userRoutine)        \
  164.             (MSeventfilterUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppMSeventfilterProcInfo, GetCurrentISA())
  165. #else
  166.     typedef tyMSeventfilter MSeventfilterUPP;
  167.     
  168.     #define CallMSeventfilterProc(userRoutine, theEvent)        \
  169.             (*(userRoutine))((theEvent))
  170.     #define NewMSeventfilterProc(userRoutine)        \
  171.             (MSeventfilterUPP)(userRoutine)
  172. #endif
  173.  
  174.  
  175. #if GENERATINGCFM
  176.     typedef UniversalProcPtr MSmenusinstallerUPP;
  177.     
  178.     #define CallMSmenusinstallerProc(userRoutine, theMenus)        \
  179.             CallUniversalProc((UniversalProcPtr)(userRoutine), uppMSmenusinstallerProcInfo, (theMenus))
  180.     #define NewMSmenusinstallerProc(userRoutine)        \
  181.             (MSmenusinstallerUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppMSmenusinstallerProcInfo, GetCurrentISA())
  182. #else
  183.     typedef tyMSmenusinstaller MSmenusinstallerUPP;
  184.     
  185.     #define CallMSmenusinstallerProc(userRoutine, theMenus)        \
  186.             (*(userRoutine))((theMenus))
  187.     #define NewMSmenusinstallerProc(userRoutine)        \
  188.             (MSmenusinstallerUPP)(userRoutine)
  189. #endif
  190.  
  191. #ifdef componentMenuSharing
  192.  
  193.     #define msComponentType 'SHMN'
  194.     #define msComponentSubType 0
  195.     
  196.     #define msInitSharedMenusCommand 0x2001 
  197.     #define msSharedMenuHitCommand 0x2002
  198.     #define msSharedScriptRunningCommand 0x2003
  199.     #define msCancelSharedScriptCommand    0x2004
  200.     #define msCheckSharedMenusCommand 0x2005
  201.     #define msDisposeSharedMenusCommand 0x2007
  202.     #define msIsSharedMenuCommand 0x2008
  203.     #define msEnableSharedMenusCommand 0x2009
  204.     #define msRunSharedMenuItemCommand 0x200A
  205.     #define msSetScriptErrorCallbackCommand 0x200B
  206.     #define msSetEventFilterCallbackCommand 0x200C
  207.     #define msSetMenusInserterCallbackCommand 0x200D
  208.     #define msSetMenusRemoverCallbackCommand 0x200E
  209.     #define msDirtySharedMenusCommand 0x200F
  210.     
  211.     #define glue static pascal ComponentResult
  212.  
  213.     
  214.     #if powerc
  215.     
  216.         enum {
  217.             uppCallComponentProcInfo = kPascalStackBased
  218.                     | RESULT_SIZE(kFourByteCode)
  219.                     | STACK_ROUTINE_PARAMETER(1, kFourByteCode)
  220.         };
  221.         
  222.         #pragma options align=mac68k
  223.         
  224.         glue initsharedmenusGlue (ComponentInstance comp) {
  225.         
  226.             #define initsharedmenusParamSize     (0L)
  227.             
  228.             struct initsharedmenusGluePB {
  229.                 unsigned char    componentFlags;
  230.                 unsigned char    componentParamSize;
  231.                 short componentWhat;
  232.                 ComponentInstance    comp;
  233.             };
  234.             
  235.             struct initsharedmenusGluePB pb;
  236.             
  237.             pb.componentFlags = 0;
  238.             pb.componentParamSize = initsharedmenusParamSize;
  239.             pb.componentWhat = msInitSharedMenusCommand;
  240.             pb.comp = comp;
  241.             
  242.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  243.             }     /*initsharedmenusGlue*/
  244.             
  245.         
  246.         glue sharedmenuhitGlue (ComponentInstance comp, short idmenu, short iditem, Boolean *flshareditem) {
  247.         
  248.             #define sharedmenuhitParamSize     (sizeof (idmenu) + sizeof (iditem) + sizeof (flshareditem))
  249.             
  250.             struct sharedmenuhitGluePB {
  251.                 unsigned char    componentFlags;
  252.                 unsigned char    componentParamSize;
  253.                 short componentWhat;
  254.                 Boolean *flshareditem;
  255.                 short iditem;
  256.                 short idmenu;
  257.                 ComponentInstance    comp;
  258.             };
  259.             
  260.             struct sharedmenuhitGluePB pb;
  261.             
  262.             pb.componentFlags = 0;
  263.             pb.componentParamSize = sharedmenuhitParamSize;
  264.             pb.componentWhat = msSharedMenuHitCommand;
  265.             pb.flshareditem = flshareditem;
  266.             pb.iditem = iditem;
  267.             pb.idmenu = idmenu;
  268.             pb.comp = comp;
  269.             
  270.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  271.             }     /*sharedmenuhitGlue*/
  272.             
  273.         
  274.         glue sharedscriptrunningGlue (ComponentInstance comp, Boolean *flrunning) {
  275.         
  276.             #define sharedscriptrunningParamSize     (sizeof (flrunning))
  277.             
  278.             struct sharedscriptrunningGluePB {
  279.                 unsigned char    componentFlags;
  280.                 unsigned char    componentParamSize;
  281.                 short componentWhat;
  282.                 Boolean *flrunning;
  283.                 ComponentInstance    comp;
  284.             };
  285.             
  286.             struct sharedscriptrunningGluePB pb;
  287.             
  288.             pb.componentFlags = 0;
  289.             pb.componentParamSize = sharedscriptrunningParamSize;
  290.             pb.componentWhat = msSharedScriptRunningCommand;
  291.             pb.flrunning = flrunning;
  292.             pb.comp = comp;
  293.             
  294.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  295.             }     /*sharedscriptrunningGlue*/
  296.             
  297.         
  298.         glue cancelsharedscriptGlue (ComponentInstance comp) {
  299.         
  300.             #define cancelsharedscriptParamSize     (0L)
  301.             
  302.             struct cancelsharedscriptGluePB {
  303.                 unsigned char    componentFlags;
  304.                 unsigned char    componentParamSize;
  305.                 short componentWhat;
  306.                 ComponentInstance    comp;
  307.             };
  308.             
  309.             struct cancelsharedscriptGluePB pb;
  310.             
  311.             pb.componentFlags = 0;
  312.             pb.componentParamSize = cancelsharedscriptParamSize;
  313.             pb.componentWhat = msCancelSharedScriptCommand;
  314.             pb.comp = comp;
  315.             
  316.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  317.             }     /*cancelsharedscriptGlue*/
  318.             
  319.         
  320.         glue checksharedmenusGlue (ComponentInstance comp, short idinsertafter) {
  321.         
  322.             #define checksharedmenusParamSize     (sizeof (idinsertafter))
  323.             
  324.             struct checksharedmenusGluePB {
  325.                 unsigned char    componentFlags;
  326.                 unsigned char    componentParamSize;
  327.                 short componentWhat;
  328.                 short idinsertafter;
  329.                 ComponentInstance    comp;
  330.             };
  331.             
  332.             struct checksharedmenusGluePB pb;
  333.             
  334.             pb.componentFlags = 0;
  335.             pb.componentParamSize = checksharedmenusParamSize;
  336.             pb.componentWhat = msCheckSharedMenusCommand;
  337.             pb.idinsertafter = idinsertafter;
  338.             pb.comp = comp;
  339.             
  340.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  341.             }     /*checksharedmenusGlue*/
  342.             
  343.         
  344.         glue disposesharedmenusGlue (ComponentInstance comp) {
  345.         
  346.             #define disposesharedmenusParamSize     (0L)
  347.             
  348.             struct disposesharedmenusGluePB {
  349.                 unsigned char    componentFlags;
  350.                 unsigned char    componentParamSize;
  351.                 short componentWhat;
  352.                 ComponentInstance    comp;
  353.             };
  354.             
  355.             struct disposesharedmenusGluePB pb;
  356.             
  357.             pb.componentFlags = 0;
  358.             pb.componentParamSize = disposesharedmenusParamSize;
  359.             pb.componentWhat = msDisposeSharedMenusCommand;
  360.             pb.comp = comp;
  361.             
  362.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  363.             }     /*disposesharedmenusGlue*/
  364.             
  365.         
  366.         glue issharedmenuGlue (ComponentInstance comp, short idmenu, Boolean *flsharedmenu) {
  367.         
  368.             #define issharedmenuParamSize     (sizeof (idmenu) + sizeof (flsharedmenu))
  369.             
  370.             struct issharedmenuGluePB {
  371.                 unsigned char    componentFlags;
  372.                 unsigned char    componentParamSize;
  373.                 short componentWhat;
  374.                 Boolean *flsharedmenu;
  375.                 short idmenu;
  376.                 ComponentInstance    comp;
  377.             };
  378.             
  379.             struct issharedmenuGluePB pb;
  380.             
  381.             pb.componentFlags = 0;
  382.             pb.componentParamSize = issharedmenuParamSize;
  383.             pb.componentWhat = msIsSharedMenuCommand;
  384.             pb.flsharedmenu = flsharedmenu;
  385.             pb.idmenu = idmenu;
  386.             pb.comp = comp;
  387.             
  388.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  389.             }     /*issharedmenuGlue*/
  390.             
  391.         
  392.         glue enablesharedmenusGlue (ComponentInstance comp, Boolean flenable) {
  393.         
  394.             #define enablesharedmenusParamSize     (sizeof (short))
  395.             
  396.             struct enablesharedmenusGluePB {
  397.                 unsigned char    componentFlags;
  398.                 unsigned char    componentParamSize;
  399.                 short componentWhat;
  400.                 Boolean flenable;
  401.                 ComponentInstance    comp;
  402.             };
  403.             
  404.             struct enablesharedmenusGluePB pb;
  405.             
  406.             pb.componentFlags = 0;
  407.             pb.componentParamSize = enablesharedmenusParamSize;
  408.             pb.componentWhat = msEnableSharedMenusCommand;
  409.             pb.flenable = flenable;
  410.             pb.comp = comp;
  411.             
  412.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  413.             }     /*enablesharedmenusGlue*/
  414.             
  415.         
  416.         glue runsharedmenuitemGlue (ComponentInstance comp, short idmenu, short iditem) {
  417.         
  418.             #define runsharedmenuitemParamSize     (sizeof (idmenu) + sizeof (iditem))
  419.             
  420.             struct runsharedmenuitemGluePB {
  421.                 unsigned char    componentFlags;
  422.                 unsigned char    componentParamSize;
  423.                 short componentWhat;
  424.                 short iditem;
  425.                 short idmenu;
  426.                 ComponentInstance    comp;
  427.             };
  428.             
  429.             struct runsharedmenuitemGluePB pb;
  430.             
  431.             pb.componentFlags = 0;
  432.             pb.componentParamSize = runsharedmenuitemParamSize;
  433.             pb.componentWhat = msRunSharedMenuItemCommand;
  434.             pb.iditem = iditem;
  435.             pb.idmenu = idmenu;
  436.             pb.comp = comp;
  437.             
  438.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  439.             }     /*runsharedmenuitemGlue*/
  440.             
  441.         
  442.         glue setscripterrorcallbackGlue (ComponentInstance comp, MSerrordialogUPP scripterrorproc) {
  443.         
  444.             #define setscripterrorcallbackParamSize     (sizeof (scripterrorproc))
  445.             
  446.             struct setscripterrorcallbackGluePB {
  447.                 unsigned char    componentFlags;
  448.                 unsigned char    componentParamSize;
  449.                 short componentWhat;
  450.                 MSerrordialogUPP scripterrorproc;
  451.                 ComponentInstance    comp;
  452.             };
  453.             
  454.             struct setscripterrorcallbackGluePB pb;
  455.             
  456.             pb.componentFlags = 0;
  457.             pb.componentParamSize = setscripterrorcallbackParamSize;
  458.             pb.componentWhat = msSetScriptErrorCallbackCommand;
  459.             pb.scripterrorproc = scripterrorproc;
  460.             pb.comp = comp;
  461.             
  462.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  463.             }     /*setscripterrorcallbackGlue*/
  464.         
  465.         
  466.         glue seteventfiltercallbackGlue (ComponentInstance comp, MSeventfilterUPP eventfilterproc) {
  467.         
  468.             #define seteventfiltercallbackParamSize     (sizeof (eventfilterproc))
  469.             
  470.             struct seteventfiltercallbackGluePB {
  471.                 unsigned char    componentFlags;
  472.                 unsigned char    componentParamSize;
  473.                 short componentWhat;
  474.                 MSeventfilterUPP eventfilterproc;
  475.                 ComponentInstance    comp;
  476.             };
  477.             
  478.             struct seteventfiltercallbackGluePB pb;
  479.             
  480.             pb.componentFlags = 0;
  481.             pb.componentParamSize = seteventfiltercallbackParamSize;
  482.             pb.componentWhat = msSetEventFilterCallbackCommand;
  483.             pb.eventfilterproc = eventfilterproc;
  484.             pb.comp = comp;
  485.             
  486.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  487.             }     /*seteventfiltercallbackGlue*/
  488.             
  489.         glue setmenusinsertercallbackGlue (ComponentInstance comp, MSmenusinstallerUPP menusinserterproc) {
  490.         
  491.             #define setmenusinsertercallbackParamSize     (sizeof (menusinserterproc))
  492.             
  493.             struct setmenusinsertercallbackGluePB {
  494.                 unsigned char    componentFlags;
  495.                 unsigned char    componentParamSize;
  496.                 short componentWhat;
  497.                 MSmenusinstallerUPP menusinserterproc;
  498.                 ComponentInstance    comp;
  499.             };
  500.             
  501.             struct setmenusinsertercallbackGluePB pb;
  502.             
  503.             pb.componentFlags = 0;
  504.             pb.componentParamSize = setmenusinsertercallbackParamSize;
  505.             pb.componentWhat = msSetMenusInserterCallbackCommand;
  506.             pb.menusinserterproc = menusinserterproc;
  507.             pb.comp = comp;
  508.             
  509.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  510.             }     /*setmenusinsertercallbackGlue*/
  511.             
  512.         glue setmenusremovercallbackGlue (ComponentInstance comp, MSmenusinstallerUPP menusremoverproc) {
  513.         
  514.             #define setmenusremovercallbackParamSize     (sizeof (menusremoverproc))
  515.             
  516.             struct setmenusremovercallbackGluePB {
  517.                 unsigned char    componentFlags;
  518.                 unsigned char    componentParamSize;
  519.                 short componentWhat;
  520.                 MSmenusinstallerUPP menusremoverproc;
  521.                 ComponentInstance    comp;
  522.             };
  523.             
  524.             struct setmenusremovercallbackGluePB pb;
  525.             
  526.             pb.componentFlags = 0;
  527.             pb.componentParamSize = setmenusremovercallbackParamSize;
  528.             pb.componentWhat = msSetMenusRemoverCallbackCommand;
  529.             pb.menusremoverproc = menusremoverproc;
  530.             pb.comp = comp;
  531.             
  532.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  533.             }     /*setmenusremovercallbackGlue*/
  534.             
  535.         glue dirtysharedmenusGlue (ComponentInstance comp) {
  536.         
  537.             #define dirtysharedmenusParamSize     (0L)
  538.             
  539.             struct dirtysharedmenusGluePB {
  540.                 unsigned char    componentFlags;
  541.                 unsigned char    componentParamSize;
  542.                 short componentWhat;
  543.                 ComponentInstance    comp;
  544.             };
  545.             
  546.             struct dirtysharedmenusGluePB pb;
  547.             
  548.             pb.componentFlags = 0;
  549.             pb.componentParamSize = dirtysharedmenusParamSize;
  550.             pb.componentWhat = msDirtySharedMenusCommand;
  551.             pb.comp = comp;
  552.             
  553.             return CallUniversalProc(CallComponentUPP, uppCallComponentProcInfo, &pb);
  554.             }     /*dirtysharedmenusGlue*/
  555.             
  556.         
  557.         #pragma options align=reset
  558.     
  559.     #else
  560.         
  561.         glue initsharedmenusGlue (ComponentInstance) /*3.0*/
  562.             
  563.             ComponentCallNow (msInitSharedMenusCommand, 0L); 
  564.             /*initsharedmenusGlue*/
  565.             
  566.         
  567.         glue sharedmenuhitGlue (ComponentInstance, short, short, Boolean *) /*3.0*/
  568.             
  569.             ComponentCallNow (msSharedMenuHitCommand, sizeof (short) + sizeof (short) + sizeof (Boolean *)); 
  570.             /*sharedmenuhitGlue*/
  571.             
  572.         
  573.         glue sharedscriptrunningGlue (ComponentInstance, Boolean *) /*3.0*/
  574.             
  575.             ComponentCallNow (msSharedScriptRunningCommand, sizeof (Boolean *));
  576.             /*sharedscriptrunningGlue*/
  577.             
  578.         
  579.         glue cancelsharedscriptGlue (ComponentInstance) /*3.0*/
  580.             
  581.             ComponentCallNow (msCancelSharedScriptCommand, 0L); 
  582.             /*cancelsharedscriptGlue*/
  583.             
  584.         
  585.         glue checksharedmenusGlue (ComponentInstance, short) /*3.0*/
  586.             
  587.             ComponentCallNow (msCheckSharedMenusCommand, sizeof (short)); 
  588.             /*checksharedmenusGlue*/
  589.             
  590.         
  591.         glue disposesharedmenusGlue (ComponentInstance) /*3.0*/
  592.             
  593.             ComponentCallNow (msDisposeSharedMenusCommand, 0L); 
  594.             /*disposesharedmenusGlue*/
  595.             
  596.         
  597.         glue issharedmenuGlue (ComponentInstance, short, Boolean *) /*3.0*/
  598.             
  599.             ComponentCallNow (msIsSharedMenuCommand, sizeof (short) + sizeof (Boolean *)); 
  600.             /*issharedmenuGlue*/
  601.             
  602.         
  603.         glue enablesharedmenusGlue (ComponentInstance, Boolean) /*3.0*/
  604.             
  605.             ComponentCallNow (msEnableSharedMenusCommand, sizeof (short)); 
  606.             /*enablesharedmenusGlue*/
  607.             
  608.         
  609.         glue runsharedmenuitemGlue (ComponentInstance, short, short) /*3.0*/
  610.             
  611.             ComponentCallNow (msRunSharedMenuItemCommand, sizeof (short) + sizeof (short)); 
  612.             /*runsharedmenuitemGlue*/
  613.             
  614.         
  615.         glue setscripterrorcallbackGlue (ComponentInstance, MSerrordialogUPP) /*3.0*/
  616.             
  617.             ComponentCallNow (msSetScriptErrorCallbackCommand, sizeof (MSerrordialogUPP)); 
  618.             /*setscripterrorcallbackGlue*/
  619.         
  620.         
  621.         glue seteventfiltercallbackGlue (ComponentInstance, MSeventfilterUPP) /*3.0*/
  622.             
  623.             ComponentCallNow (msSetEventFilterCallbackCommand, sizeof (MSeventfilterUPP)); 
  624.             /*seteventfiltercallbackGlue*/
  625.     
  626.         glue setmenusinsertercallbackGlue (ComponentInstance, MSmenusinstallerUPP) /*3.0*/
  627.             
  628.             ComponentCallNow (msSetMenusInserterCallbackCommand, sizeof (MSmenusinstallerUPP)); 
  629.             /*setmenusinsertercallbackGlue*/
  630.     
  631.         glue setmenusremovercallbackGlue (ComponentInstance, MSmenusinstallerUPP) /*3.0*/
  632.             
  633.             ComponentCallNow (msSetMenusRemoverCallbackCommand, sizeof (MSmenusinstallerUPP)); 
  634.             /*setmenusremovercallbackGlue*/
  635.     
  636.         glue dirtysharedmenusGlue (ComponentInstance) /*3.0*/
  637.             
  638.             ComponentCallNow (msDirtySharedMenusCommand, 0L); 
  639.             /*dirtysharedmenusGlue*/
  640.             
  641.         
  642.     #endif
  643.     
  644.     
  645.     static Boolean InstallEventHandlers (void); /*forward*/
  646.     
  647.     static Boolean RemoveEventHandlers (void); /*forward*/
  648.  
  649.     static Boolean HaveComponentManager (void) { /*3.0*/
  650.         
  651.         static Boolean initialized = false;
  652.         static Boolean haveit;
  653.         long result;
  654.         
  655.         if (!initialized) {
  656.             
  657.             initialized = true;
  658.             
  659.             if (Gestalt (gestaltComponentMgr, &result) != noErr)
  660.                 haveit = false;
  661.             else
  662.                 haveit = result != 0;
  663.             }
  664.             
  665.         return (haveit);
  666.         } /*HaveComponentManager*/
  667.     
  668.     
  669.     static pascal void InsertMenusCallback (hdlmenuarray hsharedmenus) {
  670.         
  671.         /*
  672.         layer to be called by the menusharing server component only
  673.         
  674.         we leave our global set to a copy of the menu array so that we 
  675.         can clean up if the server crashes
  676.         */
  677.         
  678.         hdlmenuarray hm = hsharedmenus;
  679.         
  680.         if (MSglobals.hsharedmenus != nil)
  681.             DisposeHandle ((Handle) MSglobals.hsharedmenus);
  682.         
  683.         MSglobals.hsharedmenus = hm;
  684.         
  685.         (*MSglobals.menusinsertercallback) (hm);
  686.         
  687.         HandToHand ((Handle *) &MSglobals.hsharedmenus);
  688.         } /*InsertMenusCallback*/
  689.  
  690.  
  691.     static pascal void RemoveMenusCallback (hdlmenuarray hsharedmenus) {
  692.         
  693.         /*
  694.         layer to be called by the menusharing server component only
  695.         
  696.         we leave our global set to nil when we're done
  697.         */
  698.         
  699.         hdlmenuarray hm = hsharedmenus;
  700.         
  701.         if (MSglobals.hsharedmenus != nil)
  702.             DisposeHandle ((Handle) MSglobals.hsharedmenus);
  703.         
  704.         MSglobals.hsharedmenus = hm;
  705.         
  706.         (*MSglobals.menusremovercallback) (hm);
  707.         
  708.         MSglobals.hsharedmenus = nil;
  709.         } /*RemoveMenusCallback*/
  710.  
  711.  
  712.     #if !GENERATINGCFM
  713.  
  714.         #define InsertMenusCallbackUPP InsertMenusCallback
  715.         #define RemoveMenusCallbackUPP RemoveMenusCallback
  716.  
  717.     #else
  718.  
  719.         static RoutineDescriptor InsertMenusCallbackDesc = BUILD_ROUTINE_DESCRIPTOR (uppMSmenusinstallerProcInfo, InsertMenusCallback);
  720.         static RoutineDescriptor RemoveMenusCallbackDesc = BUILD_ROUTINE_DESCRIPTOR (uppMSmenusinstallerProcInfo, RemoveMenusCallback);
  721.  
  722.         #define InsertMenusCallbackUPP (&InsertMenusCallbackDesc)
  723.         #define RemoveMenusCallbackUPP (&RemoveMenusCallbackDesc)
  724.  
  725.     #endif
  726.  
  727.  
  728.     static void ConnectWithComponent (void) { /*3.0*/
  729.         
  730.         if (!HaveComponentManager ())
  731.             return;
  732.             
  733.         if (MSglobals.menuserver != 0) /*already connected*/
  734.             return;
  735.             
  736.         MSglobals.menuserver = OpenDefaultComponent (msComponentType, msComponentSubType);
  737.         
  738.         if (MSglobals.menuserver == 0) /*didn't connect*/
  739.             return;
  740.         
  741.         MSglobals.serverversion = GetComponentVersion (MSglobals.menuserver);
  742.         
  743.         if (initsharedmenusGlue (MSglobals.menuserver) != noErr) 
  744.             goto error;
  745.         
  746.         if (setscripterrorcallbackGlue (MSglobals.menuserver, NewMSerrordialogProc (MSglobals.scripterrorcallback)) != noErr)
  747.             goto error;
  748.         
  749.         if (seteventfiltercallbackGlue (MSglobals.menuserver, NewMSeventfilterProc (MSglobals.eventfiltercallback)) != noErr)
  750.             goto error;
  751.         
  752.         if (MSglobals.serverversion >= 0x04100000) {
  753.         
  754.             setmenusinsertercallbackGlue (MSglobals.menuserver, InsertMenusCallbackUPP);
  755.             
  756.             setmenusremovercallbackGlue (MSglobals.menuserver, RemoveMenusCallbackUPP);
  757.             
  758.             RemoveEventHandlers ();    /*remove server's defaults*/
  759.             
  760.             InstallEventHandlers (); /*use ours*/
  761.             }
  762.         
  763.         return; /*everything worked*/
  764.         
  765.         error:
  766.                         
  767.         CloseComponent (MSglobals.menuserver); /*error initializing menu sharing*/
  768.                 
  769.         MSglobals.menuserver = 0;
  770.         } /*ConnectWithComponent*/
  771.     
  772. #endif
  773.  
  774.  
  775. static short CountMenuArray (void) {
  776.     
  777.     /*
  778.     return the number of menus in the menu array.
  779.     */
  780.     
  781.     hdlmenuarray hm = MSglobals.hsharedmenus;
  782.     
  783.     if (hm == nil)
  784.         return (0);
  785.     
  786.     return ((short) (GetHandleSize ((Handle) hm) / sizeof (tysharedmenurecord)));
  787.     } /*CountMenuArray*/
  788.  
  789.  
  790. #ifdef frontierMenuSharing
  791.  
  792.  
  793.     static OSType GetProcessCreator (void) {
  794.         
  795.         /*
  796.         get the 4-character creator identifier for the application we're running 
  797.         inside of.
  798.         */
  799.         
  800.         ProcessSerialNumber psn;
  801.         ProcessInfoRec info;
  802.         
  803.         GetCurrentProcess (&psn);
  804.         
  805.         info.processInfoLength = (long) sizeof (info);
  806.         
  807.         info.processName = nil;
  808.         
  809.         info.processAppSpec = nil;
  810.         
  811.         GetProcessInformation (&psn, &info);
  812.         
  813.         return (info.processSignature);
  814.         } /*GetProcessCreator*/
  815.         
  816.     
  817.     static Boolean HaveAppleEventManager (void) {
  818.     
  819.         /*
  820.         return true if Apple Events are available.
  821.         */
  822.         
  823.         long gestaltAppleEventsPresent;
  824.         
  825.         if (Gestalt (gestaltAppleEventsAttr, &gestaltAppleEventsPresent) != noErr)
  826.             return (false);
  827.         
  828.         return (gestaltAppleEventsPresent != 0);
  829.         } /*HaveAppleEventManager*/
  830.  
  831.  
  832.     static Boolean PushLongParam (long val, OSType keyword, AppleEvent *event) { /*3.0*/
  833.     
  834.         OSErr ec;
  835.         
  836.         ec = AEPutParamPtr (
  837.             
  838.             event, (AEKeyword) keyword, typeLongInteger, 
  839.             
  840.             (Ptr) &val, sizeof (long));
  841.         
  842.         return (ec == noErr);
  843.         } /*PushLongParam*/
  844.     
  845.     
  846.     static Boolean PushShortParam (short val, OSType keyword, AppleEvent *event) { /*3.0*/
  847.         
  848.         OSErr ec;
  849.         
  850.         ec = AEPutParamPtr (
  851.             
  852.             event, (AEKeyword) keyword, typeShortInteger, 
  853.             
  854.             (Ptr) &val, sizeof (short));
  855.         
  856.         return (ec == noErr);
  857.         } /*PushShortParam*/
  858.     
  859.     
  860.     static Boolean GetLongParam (AppleEvent *event, OSType keyword, long *val) { /*3.0*/
  861.         
  862.         OSErr ec;
  863.         DescType actualtype;
  864.         Size actualsize;
  865.         
  866.         ec = AEGetParamPtr (
  867.             
  868.             event, (AEKeyword) keyword, typeLongInteger, 
  869.             
  870.             &actualtype, (Ptr) val, sizeof (long), &actualsize);
  871.         
  872.         if (ec != noErr) {
  873.             
  874.             return (false);
  875.             }
  876.         
  877.         return (true);
  878.         } /*GetLongParam*/
  879.         
  880.     
  881.     static Boolean GetBinaryParam (AppleEvent *event, OSType keyword, Handle *hbinary, OSType *binarytype) { /*3.0*/
  882.         
  883.         AEDesc result;
  884.         OSErr ec;
  885.         
  886.         ec = AEGetParamDesc (event, (AEKeyword) keyword, typeWildCard, &result);
  887.         
  888.         if (ec != noErr) {
  889.             
  890.             return (false);
  891.             }
  892.         
  893.         *hbinary = result.dataHandle;
  894.         
  895.         *binarytype = result.descriptorType;
  896.         
  897.         return (true);
  898.         } /*GetBinaryParam*/
  899.     
  900.     
  901.     static Boolean SendAppleEvent (AppleEvent *event, AppleEvent *reply, Boolean noreply) { /*3.0*/
  902.     
  903.         OSErr ec;
  904.         long mode;
  905.         
  906.         if (noreply) {
  907.             
  908.             mode = kAENoReply + kAENeverInteract;
  909.          
  910.             ec = AESend (event, reply, mode, kAEHighPriority, kNoTimeOut, nil, nil);
  911.             }
  912.         else {
  913.             mode = kAEWaitReply + kAECanInteract + kAECanSwitchLayer + kAEDontRecord;
  914.             
  915.             ec = AESend (
  916.                 
  917.                 event, reply, mode, kAENormalPriority, kNoTimeOut, 
  918.                 
  919.                 nil /*(ProcPtr) IACwaitroutine*/, nil);
  920.             }
  921.         
  922.         AEDisposeDesc (event);    
  923.         
  924.         return (ec == noErr);
  925.         } /*SendAppleEvent*/
  926.     
  927.     
  928.     static Boolean ServerSupportsFastMessages (void) {
  929.         
  930.         /*
  931.         return true if there's a system event handler registered to support the
  932.         get-menu-array message. Frontier 2.0 installs such a handler, other servers
  933.         (e.g. Frontier 1.0) don't.
  934.         */
  935.         
  936.         OSErr ec;
  937.         AEEventHandlerUPP handler;
  938.         long refcon;
  939.         
  940.         ec = AEGetEventHandler (MSglobals.serverid, 'gmry', &handler, &refcon, true);
  941.         
  942.         return (ec == noErr);
  943.         } /*ServerSupportsFastMessages*/
  944.     
  945.     
  946.     static Boolean NewAppleEvent (OSType verbtoken, Boolean fast, AppleEvent *event) {
  947.         
  948.         AEAddressDesc adr;
  949.         OSErr errcode;
  950.         
  951.         if (fast && ServerSupportsFastMessages ()) {
  952.             
  953.             ProcessSerialNumber psn;
  954.             
  955.             psn.highLongOfPSN = 0;
  956.             
  957.             psn.lowLongOfPSN = kCurrentProcess;
  958.             
  959.             errcode = AECreateDesc (typeProcessSerialNumber, (Ptr) &psn, sizeof (psn), &adr);
  960.             }
  961.         else {
  962.             errcode = AECreateDesc (typeApplSignature, (Ptr) &MSglobals.serverid, sizeof (MSglobals.serverid), &adr);
  963.             }
  964.         
  965.         errcode = AECreateAppleEvent (
  966.             
  967.             MSglobals.serverid, verbtoken, &adr, kAutoGenerateReturnID, kAnyTransactionID, event);
  968.         
  969.         AEDisposeDesc (&adr);
  970.         
  971.         return (errcode == noErr);
  972.         } /*NewAppleEvent*/
  973.  
  974.  
  975.     static Boolean ProcessInForeground () {
  976.         
  977.         /*
  978.         return true if we're running in the foreground, false if we're in the
  979.         background.
  980.         */
  981.         
  982.         ProcessSerialNumber currentprocess, frontprocess;
  983.         Boolean fl;
  984.         
  985.         GetCurrentProcess (¤tprocess);
  986.         
  987.         GetFrontProcess (&frontprocess);
  988.         
  989.         SameProcess (¤tprocess, &frontprocess, &fl);
  990.         
  991.         return (fl);
  992.         } /*ProcessInForeground*/
  993.         
  994.         
  995.     static Boolean ServerIsRunning (void) {
  996.         
  997.         /*
  998.         return true if the server application is running. 
  999.         */
  1000.         
  1001.         ProcessInfoRec info;
  1002.         ProcessSerialNumber psn;
  1003.         Str255 bsname;
  1004.         FSSpec fss;
  1005.         
  1006.         info.processInfoLength = sizeof (info);
  1007.         
  1008.         info.processName = bsname; /*place to store process name*/
  1009.         
  1010.         info.processAppSpec = &fss; /*place to store process filespec*/
  1011.         
  1012.         psn.highLongOfPSN = kNoProcess;
  1013.         
  1014.         psn.lowLongOfPSN = kNoProcess;
  1015.         
  1016.         while (GetNextProcess (&psn) == noErr) {
  1017.             
  1018.              info.processInfoLength = sizeof (ProcessInfoRec);
  1019.              
  1020.             if (GetProcessInformation (&psn, &info) != noErr)
  1021.                 continue; /*keep going -- ignore error*/
  1022.             
  1023.             if (info.processSignature == MSglobals.serverid)
  1024.                 return (true);
  1025.             } /*while*/
  1026.         
  1027.         return (false); /*loop completed, no server*/
  1028.         } /*ServerIsRunning*/
  1029.     
  1030.  
  1031.     static Boolean InstallSharedMenus (void) {
  1032.         
  1033.         /*
  1034.         insert all of the menus in the menuarray into the menu bar.
  1035.         
  1036.         4.1 dmb: use menusinsertercallback to actually insert the menus
  1037.         */
  1038.         
  1039.         (*MSglobals.menusinsertercallback) (MSglobals.hsharedmenus);
  1040.         
  1041.         return (true);
  1042.         } /*InstallSharedMenus*/
  1043.     
  1044.     
  1045.     static short GetMenuHandles (void) {
  1046.         
  1047.         /*
  1048.         loop through the menuarray, send an IAC message to the menu server requesting
  1049.         that each MenuHandle be sent to us.
  1050.         */
  1051.         
  1052.         hdlmenuarray hm = MSglobals.hsharedmenus;
  1053.         short i, ct;
  1054.         AppleEvent event, reply;
  1055.         short fl;
  1056.         MenuHandle hmenu;
  1057.         OSType binarytype;
  1058.         
  1059.         ct = CountMenuArray ();
  1060.         
  1061.         for (i = 0; i < ct; i++) {
  1062.         
  1063.             if (!NewAppleEvent ('gmhd', true, &event))
  1064.                 return (false);
  1065.             
  1066.             if (!PushLongParam (MSglobals.clientid, 'menp', &event))
  1067.                 return (false);
  1068.             
  1069.             if (!PushShortParam (i, 'idix', &event))
  1070.                 return (false);
  1071.             
  1072.             if (!SendAppleEvent (&event, &reply, false))
  1073.                 return (false);
  1074.             
  1075.             fl = GetBinaryParam (&reply, keyDirectObject, (Handle *) &hmenu, &binarytype);
  1076.             
  1077.             AEDisposeDesc (&reply);
  1078.             
  1079.             if (!fl)
  1080.                 return (false);
  1081.             
  1082.             (**hm) [i].hmenu = hmenu;
  1083.             } /*for*/
  1084.         
  1085.         return (true);
  1086.         } /*GetMenuHandles*/
  1087.     
  1088.     
  1089.     static Boolean GetSharedMenus (short firstresource) {
  1090.         
  1091.         /*
  1092.         call the menu server to get a menuarray, keyed off of our application id.
  1093.         
  1094.         firstresource is the starting id to be used for the menus; if there are 
  1095.         n menus, their ids will range from firstresource to firstresource + n - 1.
  1096.         */
  1097.         
  1098.         AppleEvent event, reply;
  1099.         short fl;
  1100.         OSType binarytype;
  1101.         
  1102.         if (!NewAppleEvent ('gmry', true, &event))
  1103.             return (false);
  1104.                 
  1105.         if (!PushLongParam (MSglobals.clientid, 'menp', &event))
  1106.             return (false);
  1107.         
  1108.         if (!PushShortParam (firstresource, 'res1', &event))
  1109.             return (false);
  1110.             
  1111.         if (!SendAppleEvent (&event, &reply, false))
  1112.             return (false);
  1113.             
  1114.         fl = GetBinaryParam (&reply, keyDirectObject, (Handle *) &MSglobals.hsharedmenus, &binarytype);
  1115.         
  1116.         AEDisposeDesc (&reply);
  1117.         
  1118.         if (!fl)
  1119.             return (false);
  1120.         
  1121.         return (GetMenuHandles ());
  1122.         } /*GetSharedMenus*/
  1123.     
  1124.  
  1125.     static pascal OSErr HandleMenuDirty (const AppleEvent *event, AppleEvent *reply, long refcon) {
  1126.         
  1127.         /*
  1128.         this Apple event handler is called when the application's menu bar has been 
  1129.         edited by the script writer in the menu server's menu editor.
  1130.         
  1131.         we just record the dirty-ness of the menus in a boolean, we'll actually re-
  1132.         load the menus when we become the foreground process.
  1133.         */
  1134.         
  1135.         #pragma unused (event, reply, refcon)
  1136.         
  1137.         MSglobals.fldirtysharedmenus = true;
  1138.         
  1139.         #ifdef componentMenuSharing
  1140.         
  1141.         dirtysharedmenusGlue (MSglobals.menuserver);
  1142.         
  1143.         #endif
  1144.         
  1145.         return (noErr);
  1146.         } /*HandleMenuDirty*/
  1147.     
  1148.     
  1149.     static pascal OSErr HandleScriptComplete (const AppleEvent *event, AppleEvent *reply, long refcon) {
  1150.         
  1151.         /*
  1152.         this Apple event handler is called when a menu script has completed running.
  1153.         
  1154.         we update a couple of menu-sharing globals and re-enable the shared menus.
  1155.         
  1156.         10/8/91 DW: added callback to support Applet Toolkit.
  1157.         
  1158.         11/2/93 DW: replaced call to scriptcompletedcallback with a call to 
  1159.         scripterrorcallback if there was an error in the script.
  1160.         */
  1161.         
  1162.         #pragma unused (reply, refcon)
  1163.     
  1164.         MSglobals.flscriptcancelled = MSglobals.flscriptrunning = false;
  1165.         
  1166.         EnableSharedMenus (true);
  1167.         
  1168.         if (MSglobals.scripterrorcallback != nil) {
  1169.             
  1170.             Str255 errormessage;
  1171.             AEDesc result;
  1172.             OSErr ec;
  1173.             long lentext;
  1174.             
  1175.             ec = AEGetParamDesc (event, 'errs', typeChar, &result);
  1176.         
  1177.             if (ec != noErr) /*no error to report*/
  1178.                 return (noErr);
  1179.             
  1180.             if (result.dataHandle == nil)
  1181.                 goto exit;
  1182.             
  1183.             lentext = GetHandleSize (result.dataHandle);
  1184.         
  1185.             if (lentext > 255)
  1186.                 lentext = 255;
  1187.                 
  1188.             if (lentext == 0) /*no error to report*/
  1189.                 goto exit;
  1190.             
  1191.             errormessage [0] = (unsigned char) lentext;
  1192.         
  1193.             BlockMove (*result.dataHandle, &errormessage [1], lentext);
  1194.             
  1195.             CallMSerrordialogProc (MSglobals.scripterrorcallback, errormessage);
  1196.             
  1197.             exit:
  1198.             
  1199.             AEDisposeDesc (&result);
  1200.             }
  1201.         
  1202.         return (noErr);
  1203.         } /*HandleScriptComplete*/
  1204.     
  1205.     
  1206. #endif
  1207.         
  1208.  
  1209. static pascal void InsertSharedMenus (hdlmenuarray hsharedmenus) {
  1210.     
  1211.     /*
  1212.     insert all of the menus in the menuarray into the menu bar.  main 
  1213.     menus are inserted to the right of all others.
  1214.     
  1215.     if the menus passed in are not the same as our current global, 
  1216.     assume that we're being called from a component-based server, and 
  1217.     it owns the handle and the menus hanging off of it. dispose our 
  1218.     global and set it to a copy of those passed in, so it will still be 
  1219.     around if the server crashes and we need to get rid of them.
  1220.     */
  1221.     
  1222.     hdlmenuarray hm = hsharedmenus;
  1223.     short i;
  1224.     short ctmenus;
  1225.     tysharedmenurecord item;
  1226.     
  1227.     ctmenus = CountMenuArray ();
  1228.     
  1229.     for (i = 0; i < ctmenus; i++) {
  1230.         
  1231.         item = (**hm) [i];
  1232.         
  1233.         if (item.flhierarchic)
  1234.             InsertMenu (item.hmenu, -1);
  1235.         else
  1236.             InsertMenu (item.hmenu, 0);
  1237.         
  1238.         (**hm) [i].flinserted = true; /*so we'll know it needs to be removed*/
  1239.         } /*for*/
  1240.     } /*InsertSharedMenus*/
  1241.     
  1242.     
  1243. static pascal void RemoveSharedMenus (hdlmenuarray hsharedmenus) {
  1244.     
  1245.     /*
  1246.     remove the shared menus from the menubar, reversing the action of InsertSharedMenus.
  1247.     
  1248.     Unless, for some strange reason, we installed a menuinserter callback that 
  1249.     didn't set MSglobals.hsharedmenus, we can safely ignore the menus parameter.
  1250.     
  1251.     note that we carefully avoid disposing anything, a requirement for working 
  1252.     with component menusharing. But we must clear the hsharedmenus global to 
  1253.     maintain a consistent state.
  1254.     */
  1255.     
  1256.     hdlmenuarray hm = hsharedmenus;
  1257.     short i;
  1258.     short ctmenus;
  1259.     tysharedmenurecord item;
  1260.     
  1261.     ctmenus = CountMenuArray ();
  1262.     
  1263.     for (i = 0; i < ctmenus; i++) {
  1264.         
  1265.         item = (**hm) [i];
  1266.         
  1267.         if (item.flinserted)
  1268.             DeleteMenu (item.idmenu);
  1269.         } /*for*/    
  1270.     } /*RemoveSharedMenus*/
  1271.  
  1272.  
  1273. pascal Boolean DisposeSharedMenus (void) {
  1274.     
  1275.     /*
  1276.     completely dispose of the menuarray and the menu handles it contains.
  1277.     
  1278.     10/10/91 DW: check for no shared menus before disposing, save code if 
  1279.     its ever called from more than one place. also set the global handle to
  1280.     nil after disposing and redraw the menu bar.
  1281.     
  1282.     4.1 dmb: use menusremovercallback to actually remove the menus
  1283.     */
  1284.     
  1285.     hdlmenuarray hm = MSglobals.hsharedmenus;
  1286.     short i;
  1287.     short ctmenus;
  1288.     tysharedmenurecord item;
  1289.     
  1290.     #ifdef componentMenuSharing
  1291.     
  1292.         if (MSglobals.menuserver != 0) /*3.0*/
  1293.             return (disposesharedmenusGlue (MSglobals.menuserver) == noErr);
  1294.         
  1295.     #endif
  1296.     
  1297.     #ifdef frontierMenuSharing
  1298.     
  1299.         MSglobals.fldirtysharedmenus = true; /*4.1 dmb: for clients with dynamic menubars*/
  1300.         
  1301.         if (hm == nil) /*no shared menus to toss*/
  1302.             return (true);
  1303.         
  1304.         (*MSglobals.menusremovercallback) (hm);
  1305.         
  1306.         ctmenus = CountMenuArray ();
  1307.         
  1308.         for (i = 0; i < ctmenus; i++) {
  1309.             
  1310.             item = (**hm) [i];
  1311.             
  1312.             DisposeMenu (item.hmenu);
  1313.             } /*for*/
  1314.         
  1315.         DisposeHandle ((Handle) hm);
  1316.         
  1317.         MSglobals.hsharedmenus = nil;
  1318.         
  1319.         DrawMenuBar ();
  1320.         
  1321.         return (true);
  1322.     
  1323.     #endif
  1324.  
  1325.     return (false);   /* JWB 5/4/95 */
  1326.     } /*DisposeSharedMenus*/
  1327.  
  1328.  
  1329. pascal Boolean IsSharedMenu (short idmenu) {
  1330.     
  1331.     /*
  1332.     return true if the indicated menu is one of the shared menus.
  1333.     */
  1334.     
  1335.     hdlmenuarray hm = MSglobals.hsharedmenus;
  1336.     short ct, i;
  1337.     tysharedmenurecord item;
  1338.     
  1339.     #ifdef componentMenuSharing
  1340.     
  1341.         /*3.0*/ {
  1342.         
  1343.             Boolean flshared;
  1344.             
  1345.             if (MSglobals.menuserver != 0) {
  1346.                 
  1347.                 if (issharedmenuGlue (MSglobals.menuserver, idmenu, &flshared) == noErr)
  1348.                     return (flshared);
  1349.                     
  1350.                 return (false);
  1351.                 }
  1352.             }
  1353.     #endif
  1354.     
  1355.     #ifdef frontierMenuSharing
  1356.     
  1357.         ct = CountMenuArray ();
  1358.         
  1359.         for (i = 0; i < ct; i++) {
  1360.             
  1361.             item = (**hm) [i];
  1362.             
  1363.             if (item.idmenu == idmenu)
  1364.                 return (true);
  1365.             } /*for*/
  1366.             
  1367.         return (false);
  1368.         
  1369.     #endif
  1370.     
  1371.     return (false);  /* JWB 5/4/95 */
  1372.     } /*IsSharedMenu*/
  1373.  
  1374.  
  1375. pascal Boolean EnableSharedMenus (Boolean flenable) {
  1376.     
  1377.     /*
  1378.     Enables or disables the the menus in the specified menu array.
  1379.     
  1380.     Always returns true.
  1381.     */
  1382.     
  1383.     hdlmenuarray hm = MSglobals.hsharedmenus;
  1384.     short i;
  1385.     short ctmenus;
  1386.     MenuHandle hmenu;
  1387.     
  1388.     #ifdef componentMenuSharing
  1389.     
  1390.         if (MSglobals.menuserver != 0) /*3.0*/
  1391.             return (enablesharedmenusGlue (MSglobals.menuserver, flenable) == noErr);
  1392.     
  1393.     #endif
  1394.     
  1395.     #ifdef frontierMenuSharing
  1396.         
  1397.         ctmenus = CountMenuArray ();
  1398.         
  1399.         for (i = 0; i < ctmenus; i++) {
  1400.             
  1401.             hmenu = (**hm) [i].hmenu;
  1402.             
  1403.             if (flenable)
  1404.                 EnableItem (hmenu, 0);
  1405.             else
  1406.                 DisableItem (hmenu, 0);
  1407.             } /*for*/
  1408.         
  1409.         DrawMenuBar ();
  1410.         
  1411.         return (true);
  1412.         
  1413.     #endif
  1414.     
  1415.     return (false); /* JWB 5/4/95 */
  1416.     } /*EnableSharedMenus*/
  1417.  
  1418.  
  1419. pascal Boolean RunSharedMenuItem (short idmenu, short iditem) {
  1420.      
  1421.     /*
  1422.     call the menu server to run the script linked to the indicated menu item.
  1423.     
  1424.     the script will execute asynchonously, after this call returns.
  1425.     
  1426.     SDK 2.0: if the server isn't running, remove the shared menus and return
  1427.     false. this will only happen if the server has crashed without letting us
  1428.     know that our menus are dirty.
  1429.     */
  1430.     
  1431.     AppleEvent event, reply;
  1432.     Boolean fl;
  1433.     
  1434.     if (!MSglobals.flinitialized) /*3.0*/
  1435.         return (false);
  1436.     
  1437.     #ifdef componentMenuSharing
  1438.     
  1439.         if (MSglobals.menuserver != 0) /*3.0*/
  1440.             return (runsharedmenuitemGlue (MSglobals.menuserver, idmenu, iditem) == noErr);
  1441.             
  1442.     #endif
  1443.     
  1444.     #ifdef frontierMenuSharing
  1445.     
  1446.         if (!ServerIsRunning ()) {
  1447.             
  1448.             MSglobals.fldirtysharedmenus = true;
  1449.             
  1450.             return (false);
  1451.             }
  1452.         
  1453.         if (!NewAppleEvent ('runm', false, &event))
  1454.             return (false);
  1455.         
  1456.         if (!PushLongParam (MSglobals.clientid, 'menp', &event))
  1457.             return (false);
  1458.         
  1459.         if (!PushShortParam (idmenu, 'mid ', &event))
  1460.             return (false);
  1461.         
  1462.         if (!PushShortParam (iditem, 'mitm', &event))
  1463.             return (false);
  1464.         
  1465.         if (!SendAppleEvent (&event, &reply, false))
  1466.             return (false);
  1467.         
  1468.         fl = GetLongParam (&reply, keyDirectObject, &MSglobals.idscript);
  1469.         
  1470.         AEDisposeDesc (&reply);
  1471.         
  1472.         return (fl && (MSglobals.idscript != 0));
  1473.         
  1474.     #endif
  1475.     
  1476.     return (false);  /* JWB 5/4/95 */
  1477.     } /*RunSharedMenuItem*/
  1478.  
  1479.  
  1480. pascal Boolean CheckSharedMenus (short idinsertafter) {
  1481.     
  1482.     /*
  1483.     call this from your main event loop after receiving and processing every
  1484.     event. if the menus need updating, we send a message to the server asking
  1485.     for our shared menus.
  1486.     
  1487.     if we load menus, they are assigned resource ids starting with idinsertafter.
  1488.     this number must be less than 255 to allow for hierarchic menus, and must be
  1489.     small enough so that no menu has an id of greater than 255. 
  1490.     
  1491.     9/28/91 DW: only update menus if we're the front process. this catches the
  1492.     delay on re-loading a changed menu structure on the Multifinder switch. No
  1493.     extra burden on the script writer editing the menu bar.
  1494.     
  1495.     11/1/93 DW: add support for component menu sharing. 
  1496.     
  1497.     11/16/93 dmb: clear MSglobals.menuserver if we get a badComponentInstance error. 
  1498.     the next call to CheckSharedMenus will attempt to reconnect.
  1499.     
  1500.     7/16/96 dmb: if the component menuserver goes bad, remove the event handler that
  1501.     it installed on our behalf. it may be orphanced code now if the server crashed.
  1502.     */
  1503.     
  1504.     #ifdef componentMenuSharing
  1505.     
  1506.         /*3.0*/ {
  1507.         
  1508.             ConnectWithComponent (); /*does nothing if already connected*/
  1509.             
  1510.             if (MSglobals.menuserver != 0) {
  1511.                 
  1512.                 if (checksharedmenusGlue (MSglobals.menuserver, idinsertafter) == badComponentInstance) {
  1513.                         
  1514.                     if (MSglobals.hsharedmenus != nil) { /*dmb 4.1*/
  1515.                     
  1516.                         (*MSglobals.menusremovercallback) (MSglobals.hsharedmenus);
  1517.                         
  1518.                         DisposeHandle ((Handle) MSglobals.hsharedmenus);
  1519.                     
  1520.                         MSglobals.hsharedmenus = nil;
  1521.                         
  1522.                         DrawMenuBar ();
  1523.                         }
  1524.                     
  1525.                     RemoveEventHandlers (); /*dmb 4.1*/
  1526.                     
  1527.                     MSglobals.menuserver = 0;
  1528.                     
  1529.                     return (false);
  1530.                     }
  1531.                 
  1532.                 return (true);
  1533.                 }
  1534.             }
  1535.         
  1536.     #endif
  1537.     
  1538.     #ifdef frontierMenuSharing
  1539.     
  1540.         if (!ProcessInForeground ()) /*only update menus if we're the front process*/
  1541.             return (true);
  1542.         
  1543.         if (!MSglobals.fldirtysharedmenus) /*no need for an update, return quickly*/
  1544.             return (true);
  1545.             
  1546.         DisposeSharedMenus ();
  1547.         
  1548.         if (ServerIsRunning ()) {
  1549.         
  1550.             if (GetSharedMenus (idinsertafter)) {
  1551.         
  1552.                 InstallSharedMenus (); /*install to the right of all other menus*/
  1553.                 
  1554.                 DrawMenuBar ();
  1555.                 }
  1556.             
  1557.             MSglobals.fldirtysharedmenus = false;
  1558.             }
  1559.             
  1560.         else { /*server not running, menus have been updated (ie there are no shared menus)*/
  1561.         
  1562.             MSglobals.fldirtysharedmenus = false;
  1563.             }
  1564.             
  1565.         return (true);
  1566.     
  1567.     #endif
  1568.     
  1569.     return (false); /* JWB 5/4/95 */
  1570.     } /*CheckSharedMenus*/
  1571.     
  1572.     
  1573. pascal Boolean SharedScriptRunning () {
  1574.     
  1575.     /*
  1576.     returns true if a shared script is currently running, false otherwise.
  1577.     
  1578.     it's provided so that an application can intelligently handle cmd-period
  1579.     script termination in its keystroke handling routine.
  1580.     */
  1581.     
  1582.     return (MSglobals.flscriptrunning);
  1583.     } /*SharedScriptRunning*/
  1584.     
  1585.  
  1586. pascal Boolean CancelSharedScript () {
  1587.     
  1588.     /*
  1589.     call this when the user presses cmd-period or otherwise indicates to you that
  1590.     he or she wants the currently running script to be halted. 
  1591.         
  1592.     8/13/92 DW: if we're talking to post-2.0 Frontier or Runtime 1.0, we send a
  1593.     message to the server telling it to kill the script. otherwise we do it the
  1594.     old less elegant way, by setting a flag that gets monitored in calls to 
  1595.     SharedScriptCancelled.
  1596.     */
  1597.     
  1598.     #ifdef frontierMenuSharing
  1599.     
  1600.         AppleEvent event, reply;
  1601.      
  1602.         if (!MSglobals.flscriptrunning) /*nothing to do*/
  1603.             return (true);
  1604.             
  1605.         if (!ServerSupportsFastMessages ()) {
  1606.             
  1607.             MSglobals.flscriptcancelled = true;
  1608.             
  1609.             return (true);
  1610.             }
  1611.       
  1612.         if (!NewAppleEvent ('kill', false, &event))
  1613.             return (false);
  1614.         
  1615.         if (!PushLongParam (MSglobals.idscript, '----', &event))
  1616.             return (false);
  1617.         
  1618.         if (!SendAppleEvent (&event, &reply, true))
  1619.             return (false);
  1620.     
  1621.         return (true);
  1622.     
  1623.     #endif
  1624.     } /*CancelSharedScript*/
  1625.  
  1626.  
  1627. pascal Boolean SharedMenuHit (short idmenu, short iditem) {
  1628.  
  1629.     /*
  1630.     returns true if the indicated menu and item indicate a shared menu item.
  1631.     
  1632.     if not, we return false -- the item is in one of your menus, you should
  1633.     process the command as you normally would.
  1634.     
  1635.     we send an IAC message to the menu server, requesting that the script
  1636.     linked into that item be run.
  1637.     
  1638.     we disable the shared menus, awaiting a 'done' message to re-enable them.
  1639.     */
  1640.     
  1641.     if (!MSglobals.flinitialized) /*3.0*/
  1642.         return (false);
  1643.     
  1644.     #ifdef componentMenuSharing
  1645.     
  1646.         /*3.0*/ {
  1647.         
  1648.             Boolean flshareditem;
  1649.         
  1650.             if (MSglobals.menuserver != 0) {
  1651.                 
  1652.                 if (sharedmenuhitGlue (MSglobals.menuserver, idmenu, iditem, &flshareditem) != noErr)
  1653.                     return (false);
  1654.                 
  1655.                 return (flshareditem); /*client handles if it wasn't a shared item*/
  1656.                 }
  1657.             }
  1658.     #endif
  1659.     
  1660.     #ifdef frontierMenuSharing
  1661.     
  1662.         if (!IsSharedMenu (idmenu)) /*not a shared menu*/
  1663.             return (false);
  1664.             
  1665.         HiliteMenu (0);
  1666.             
  1667.         if (RunSharedMenuItem (idmenu, iditem)) {
  1668.         
  1669.             MSglobals.flscriptrunning = true;
  1670.         
  1671.             EnableSharedMenus (false);
  1672.             }
  1673.                 
  1674.         return (true);
  1675.         
  1676.     #endif
  1677.     
  1678.     return (false);  /* covers the case when Frontier is not running, and only Component Menu Sharing
  1679.                         is enabled. JWB 5/4/95 */
  1680.     } /*SharedMenuHit*/
  1681.     
  1682.  
  1683. pascal Boolean SharedScriptCancelled (AppleEvent *event, AppleEvent *reply) {
  1684.     
  1685.     /*
  1686.     call this routine in each Apple event message handler that could conceivably 
  1687.     be used in a script being run by the menu server. if we return false continue
  1688.     processing the message as you normally would. if we return true, that means
  1689.     that the script that's running has been cancelled by the user; you should 
  1690.     return noErr from your Apple event handler when we return true.
  1691.     
  1692.     before we return true, we reply to the message on behalf of the message
  1693.     handler. we send a specific error code of 6, this should be interpreted by
  1694.     the scripting system as "stop running the script, but don't display an
  1695.     error dialog.
  1696.     
  1697.     we admit this mechanism is somewhat klunky, but it proved too difficult to have
  1698.     Frontier be ready to respond to a "Cancel Script" Apple event while running
  1699.     the script and also giving time slices to agents.
  1700.     
  1701.     12/16/92 dmb: this minimal version supports the old protocol, but it's not 
  1702.     needed for Frontier/Runtime 2.0 and greater.
  1703.     
  1704.     11/2/93 DW: this klunky method is no longer recommended, but it is still
  1705.     supported.
  1706.     */
  1707.     
  1708.     #pragma unused (event)
  1709.     
  1710.     #ifdef frontierMenuSharing
  1711.  
  1712.         if (MSglobals.flscriptcancelled && MSglobals.flscriptrunning) {
  1713.             
  1714.             MSglobals.flscriptcancelled = MSglobals.flscriptrunning = false;
  1715.             
  1716.             PushLongParam (6, keyErrorNumber, reply); /*server watches for this special error code*/
  1717.             
  1718.             return (true);
  1719.             }
  1720.             
  1721.         return (false); /*script not cancelled, keep processing message*/
  1722.     
  1723.     #else
  1724.     
  1725.         #pragma unused (reply)
  1726.     
  1727.     #endif
  1728.     } /*SharedScriptCancelled*/
  1729.     
  1730.  
  1731. pascal Boolean SetMenusInserterCallback (tyMSmenusinstaller menusinserter) {
  1732.     
  1733.     MSglobals.menusinsertercallback = menusinserter;
  1734.     
  1735.     return (true);
  1736.     } /*SetMenusInserterCallback*/
  1737.  
  1738.  
  1739. pascal Boolean SetMenusRemoverCallback (tyMSmenusinstaller menusremover) {
  1740.  
  1741.     MSglobals.menusremovercallback = menusremover;
  1742.     
  1743.     return (true);
  1744.     } /*SetMenusRemoverCallback*/
  1745.  
  1746.  
  1747. static Boolean InstallEventHandlers (void) {
  1748.     
  1749.     if (AEInstallEventHandler (MSglobals.clientid, 'updm', NewAEEventHandlerProc (HandleMenuDirty), 0, false) != noErr)
  1750.         return (false);
  1751.     
  1752.     #ifdef frontierMenuSharing
  1753.     
  1754.     if (AEInstallEventHandler (MSglobals.clientid, 'done', NewAEEventHandlerProc (HandleScriptComplete), 0, false) != noErr)
  1755.         return (false);
  1756.     
  1757.     #endif
  1758.     
  1759.     return (true);
  1760.     } /*InstallEventHandlers*/
  1761.  
  1762.  
  1763. static Boolean RemoveEventHandlers (void) {
  1764.     
  1765.     if (AERemoveEventHandler (MSglobals.clientid, 'updm', nil, false) != noErr)
  1766.         return (false);
  1767.     
  1768.     #ifdef frontierMenuSharing
  1769.     
  1770.     if (AERemoveEventHandler (MSglobals.clientid, 'done', nil, false) != noErr)
  1771.         return (false);
  1772.     
  1773.     #endif
  1774.     
  1775.     return (true);
  1776.     } /*RemoveEventHandlers*/
  1777.  
  1778.  
  1779. pascal Boolean InitSharedMenus (tyMSerrordialog errordialogcallback, tyMSeventfilter eventfiltercallback) {
  1780.  
  1781.     /*
  1782.     sets the program up for menu sharing. we initialize the IAC Tools library and
  1783.     then initialize the fields of MSglobals. 
  1784.     
  1785.     we install two Apple event message handlers -- one to catch the "menu needs update" 
  1786.     message, and another to handle the "script has completed" message.
  1787.     
  1788.     11/2/93 DW: Complete rewrite for 3.0.
  1789.     */
  1790.     
  1791.     MSglobals.flinitialized = false; 
  1792.     
  1793.     MSglobals.scripterrorcallback = errordialogcallback; 
  1794.         
  1795.     MSglobals.menusinsertercallback = InsertSharedMenus;
  1796.     
  1797.     MSglobals.menusremovercallback = RemoveSharedMenus;
  1798.  
  1799.     if (!HaveAppleEventManager ())
  1800.         return (false);
  1801.     
  1802.     #ifdef componentMenuSharing
  1803.         
  1804.         MSglobals.menuserver = 0; 
  1805.     
  1806.         MSglobals.eventfiltercallback = eventfiltercallback; 
  1807.     
  1808.         MSglobals.flinitialized = true; 
  1809.     
  1810.     #endif
  1811.     
  1812.     MSglobals.serverid = 'LAND'; /*Frontier's creator id, for pre-3.0 protocol only*/
  1813.  
  1814.     MSglobals.clientid = GetProcessCreator (); 
  1815.  
  1816.     MSglobals.hsharedmenus = nil; /*haven't loaded shared menus yet*/
  1817.     
  1818.     MSglobals.fldirtysharedmenus = true; /*force update 1st time thru event loop*/
  1819.  
  1820.     MSglobals.flscriptcancelled = false; /*script hasn't been cancelled*/
  1821.  
  1822.     MSglobals.flscriptrunning = false; /*no menu script running*/
  1823.     
  1824.     MSglobals.flinitialized = true; 
  1825.  
  1826.     if (!InstallEventHandlers ())
  1827.         return (false);
  1828.     
  1829.     return (true);
  1830.     } /*InitSharedMenus*/
  1831.  
  1832.  
  1833.     
  1834.